1 # ---------------------------------------------------------------------------
3 # Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
4 # ---------------------------------------------------------------------------
5 # SquirrelJME is under the Mozilla Public License Version 2.0.
6 # See license.mkd for licensing and copyright information.
7 # ---------------------------------------------------------------------------
8 # DESCRIPTION: Defines the base project and the versioning info
10 # Echo commands accordingly
11 set(CMAKE_EXECUTE_PROCESS_COMMAND_ECHO STDERR)
14 if(NOT DEFINED SQUIRRELJME_UTIL_CMAKE_WHERE)
15 set(SQUIRRELJME_UTIL_CMAKE_WHERE "${CMAKE_CURRENT_LIST_DIR}")
18 if(NOT DEFINED SQUIRRELJME_UTIL_CMAKE_WHERE)
19 set(SQUIRRELJME_UTIL_CMAKE_WHERE "${CMAKE_SOURCE_DIR}")
22 # The directory where the utilities should exist
23 get_filename_component(SQUIRRELJME_UTIL_SOURCE_DIR
24 "${SQUIRRELJME_UTIL_CMAKE_WHERE}/utils" ABSOLUTE)
25 get_filename_component(SQUIRRELJME_UTIL_DIR
26 "${CMAKE_BINARY_DIR}/utils" ABSOLUTE)
28 # Add macro to determine the path of a utility
29 macro(squirreljme_util var what)
31 "${SQUIRRELJME_UTIL_DIR}/${what}${SQUIRRELJME_HOST_EXE_SUFFIX}")
34 # If we are on Windows, we do want to pass our generator
35 message(STATUS "CMake Generator Platform: ${CMAKE_GENERATOR_PLATFORM}")
36 if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
37 unset(SQUIRRELJME_SWITCH_CMAKE_GENERATOR_PLATFORM_UNSET)
38 set(SQUIRRELJME_SWITCH_CMAKE_GENERATOR_PLATFORM_SET
39 "-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}")
41 set(SQUIRRELJME_SWITCH_CMAKE_GENERATOR_PLATFORM_UNSET
42 "--unset=CMAKE_GENERATOR_PLATFORM")
43 unset(SQUIRRELJME_SWITCH_CMAKE_GENERATOR_PLATFORM_SET)
46 # Need to cleanup any previous configuration run before building
47 if(EXISTS "${SQUIRRELJME_UTIL_DIR}/CMakeCache.txt" OR
48 (EXISTS "${SQUIRRELJME_UTIL_DIR}" AND
49 IS_DIRECTORY "${SQUIRRELJME_UTIL_DIR}"))
50 file(REMOVE_RECURSE "${SQUIRRELJME_UTIL_DIR}/")
53 # Make sure the resultant utility directory exists
54 file(MAKE_DIRECTORY "${SQUIRRELJME_UTIL_DIR}")
56 # Try to find the host CMake as a first choice
57 find_program(SJME_FIRST_CMAKE "cmake" NO_DEFAULT_PATH)
58 if(NOT SJME_FIRST_CMAKE)
59 find_program(SJME_FIRST_CMAKE "cmake")
61 if(NOT SJME_FIRST_CMAKE)
62 set(SJME_FIRST_CMAKE "${CMAKE_COMMAND}")
66 # Double check version
67 execute_process(COMMAND "${SJME_FIRST_CMAKE}" "-version"
68 OUTPUT_FILE "${CMAKE_BINARY_DIR}/first-cmake-version")
69 file(STRINGS "${CMAKE_BINARY_DIR}/first-cmake-version" SJME_FIRST_CMAKE_VER
71 string(TOLOWER "${SJME_FIRST_CMAKE_VER}" SJME_FIRST_CMAKE_VER)
72 string(REPLACE "cmake version " ""
73 SJME_FIRST_CMAKE_VER "${SJME_FIRST_CMAKE_VER}")
75 # If the CMake we found is too old, ignore it and use our current one
76 message(STATUS "CMake ${SJME_FIRST_CMAKE} is ${SJME_FIRST_CMAKE_VER}")
77 if("${SJME_FIRST_CMAKE_VER}" VERSION_LESS 3.0)
79 message(STATUS "Using ${CMAKE_COMMAND} as it is too old...")
81 # Just use our version
82 set(SJME_FIRST_CMAKE "${CMAKE_COMMAND}")
85 # Setup command to run
87 list(APPEND SJME_UTIL_CFG "${SJME_FIRST_CMAKE}")
88 list(APPEND SJME_UTIL_CFG "-E")
89 list(APPEND SJME_UTIL_CFG "env")
90 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_TOOLCHAIN")
91 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_TOOLCHAIN_FILE")
92 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_SOURCE_ROOT")
93 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_FRAMEWORK_PATH")
94 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_INCLUDE_PATH")
95 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_LIBRARY_PATH")
96 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_PROGRAM_PATH")
97 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_BUILD_TYPE")
98 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_GENERATOR")
99 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_GENERATOR_INSTANCE")
100 list(APPEND SJME_UTIL_CFG ${SQUIRRELJME_SWITCH_CMAKE_GENERATOR_PLATFORM_UNSET})
101 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_GENERATOR_TOOLSET")
102 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_C_COMPILER_LAUNCHER")
103 list(APPEND SJME_UTIL_CFG "--unset=CMAKE_C_LINKER_LAUNCHER")
104 list(APPEND SJME_UTIL_CFG "--unset=CC")
105 list(APPEND SJME_UTIL_CFG "--unset=CXX")
106 list(APPEND SJME_UTIL_CFG "--unset=CFLAGS")
107 list(APPEND SJME_UTIL_CFG "--unset=CXXFLAGS")
108 list(APPEND SJME_UTIL_CFG "--unset=LDFLAGS")
110 # Target CMake Command
111 list(APPEND SJME_UTIL_CFG "${SJME_FIRST_CMAKE}")
112 list(APPEND SJME_UTIL_CFG "-DCMAKE_BUILD_TYPE=Debug")
113 list(APPEND SJME_UTIL_CFG "-DCMAKE_SYSTEM_NAME=${CMAKE_HOST_SYSTEM_NAME}")
114 list(APPEND SJME_UTIL_CFG
115 "-DCMAKE_SYSTEM_PROCESSOR=${CMAKE_HOST_SYSTEM_PROCESSOR}")
116 list(APPEND SJME_UTIL_CFG ${SQUIRRELJME_SWITCH_CMAKE_GENERATOR_PLATFORM_SET})
118 if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.13" AND
119 "${SJME_FIRST_CMAKE_VER}" VERSION_GREATER_EQUAL "3.13")
120 list(APPEND SJME_UTIL_CFG "-S" "${SQUIRRELJME_UTIL_SOURCE_DIR}")
121 list(APPEND SJME_UTIL_CFG "-B" "${SQUIRRELJME_UTIL_DIR}")
123 list(APPEND SJME_UTIL_CFG "${SQUIRRELJME_UTIL_SOURCE_DIR}")
127 message(STATUS "Bootstrapping utils into "
128 "${SQUIRRELJME_UTIL_DIR}...")
129 message(STATUS "Current generator is ${CMAKE_GENERATOR}...")
132 message(STATUS "CONFIGURE: -------------------------------------------------")
136 COMMAND ${SJME_UTIL_CFG}
137 WORKING_DIRECTORY "${SQUIRRELJME_UTIL_DIR}"
138 RESULT_VARIABLE SJME_UTIL_CFG_RESULT)
141 if(NOT SJME_UTIL_CFG_RESULT EQUAL 0)
142 message(FATAL_ERROR "Configure failed with: ${SJME_UTIL_CFG_RESULT}")
146 message(STATUS "BUILD: -----------------------------------------------------")
150 COMMAND "${SJME_FIRST_CMAKE}"
151 "--build" "${SQUIRRELJME_UTIL_DIR}"
152 RESULT_VARIABLE SJME_UTIL_BLD_RESULT
153 WORKING_DIRECTORY "${SQUIRRELJME_UTIL_DIR}")
156 if(NOT SJME_UTIL_BLD_RESULT EQUAL 0)
157 message(FATAL_ERROR "Build failed with: ${SJME_UTIL_BLD_RESULT}")
161 message(STATUS "PREFIX/SUFFIX: ---------------------------------------------")
163 # Determine executable suffix
164 if(EXISTS "${SQUIRRELJME_UTIL_DIR}/suffix")
165 file(STRINGS "${SQUIRRELJME_UTIL_DIR}/suffix"
166 SQUIRRELJME_HOST_EXE_SUFFIX)
167 message(DEBUG "Host executable suffix is "
168 "'${SQUIRRELJME_HOST_EXE_SUFFIX}'.")
171 # Determine dynamic library prefix
172 if(EXISTS "${SQUIRRELJME_UTIL_DIR}/dylibprefix")
173 file(STRINGS "${SQUIRRELJME_UTIL_DIR}/dylibprefix"
174 SQUIRRELJME_HOST_DYLIB_PREFIX)
175 message(DEBUG "Host library prefix is "
176 "'${SQUIRRELJME_HOST_DYLIB_PREFIX}'.")
179 # Determine dynamic library suffix
180 if(EXISTS "${SQUIRRELJME_UTIL_DIR}/dylibsuffix")
181 file(STRINGS "${SQUIRRELJME_UTIL_DIR}/dylibsuffix"
182 SQUIRRELJME_HOST_DYLIB_SUFFIX)
183 message(DEBUG "Host library suffix is "
184 "'${SQUIRRELJME_HOST_DYLIB_SUFFIX}'.")
188 message(STATUS "SIMPLE CHECK: ----------------------------------------------")
190 # Try running simple utility to make sure it compiled under the host
191 squirreljme_util(SJME_UTIL_SIMPLE simple)
192 execute_process(COMMAND "${SJME_UTIL_SIMPLE}"
193 RESULT_VARIABLE SJME_UTIL_CHK_RESULT
194 WORKING_DIRECTORY "${SQUIRRELJME_UTIL_DIR}")
196 # Make sure it is actually valid
197 if(NOT SJME_UTIL_CHK_RESULT EQUAL 0)
198 message(FATAL_ERROR "Simple run failed with: ${SJME_UTIL_CHK_RESULT}")
202 message(STATUS "------------------------------------------------------------")
204 # ----------------------------------------------------------------------------
206 # Checks if a given file is out of date according to a checksum
207 function(squirreljme_check_file_checksum upToDateVar
208 inputFile outputPath)
209 # Get hash of input file
210 file(SHA1 "${inputFile}" cacheHash)
212 # Get last checksum, if any
213 if(EXISTS "${outputPath}.checksum")
214 file(STRINGS "${outputPath}.checksum"
217 set(cacheHashLast "")
220 # Is the checksum out of date?
221 if(NOT EXISTS "${outputPath}.checksum" OR
222 NOT EXISTS "${outputPath}" OR
223 NOT "${cacheHash}" STREQUAL "${cacheHashLast}")
224 set(${upToDateVar} 0 PARENT_SCOPE)
226 set(${upToDateVar} 1 PARENT_SCOPE)
230 # Writes the checksum of the input file to the output
231 function(squirreljme_write_file_checksum inputFile
233 # Get hash of input file
234 file(SHA1 "${inputFile}" cacheHash)
237 file(WRITE "${outputPath}.checksum"
241 # Decodes the given file
242 function(squirreljme_decode_file how
243 inputPath outputPath)
244 # Should be HEX or BASE64
245 if(NOT how STREQUAL "HEX" AND
246 NOT how STREQUAL "BASE64")
247 message(FATAL_ERROR "squirreljme_decode_file() takes "
248 "either HEX or BASE64")
251 # Where is the decoder?
252 squirreljme_util(decodeExePath decode)
255 execute_process(COMMAND "${decodeExePath}" "${how}"
256 INPUT_FILE "${inputPath}"
257 OUTPUT_FILE "${outputPath}"
258 RESULT_VARIABLE conversionExitCode
262 if(conversionExitCode)
264 "Conversion failed: ${conversionExitCode}.")
268 # Decodes a directory of encoded files
269 function(squirreljme_decode_dir inputDir outputDir)
270 # Decode all files accordingly
272 "${inputDir}/*.__hex"
273 "${inputDir}/*.__mime")
274 foreach(inFile ${inFiles})
275 # Determine the base name of the file
276 get_filename_component(baseName
279 # Is this Hex or MIME?
280 string(FIND "${baseName}" ".__hex"
283 # Remove extension from it
284 string(REPLACE ".__hex" ""
287 string(REPLACE ".__mime" ""
291 # Make sure the target directory exists first
292 file(MAKE_DIRECTORY "${outputDir}")
294 # Determine input and output
295 get_filename_component(inFileAbs
296 "${inFile}" ABSOLUTE)
297 get_filename_component(outFileAbsPath
298 "${outputDir}/${baseName}" ABSOLUTE)
300 # Check if file is up to date
301 squirreljme_check_file_checksum(upToDate
302 "${inFileAbs}" "${outFileAbsPath}")
304 # Does decoding need to be rerun?
306 # Run decoding sequence
308 "Decoding ${inFileAbs} to "
309 "${outFileAbsPath}...")
310 file(REMOVE "${outFileAbsPath}")
312 squirreljme_decode_file(BASE64
313 "${inFileAbs}" "${outFileAbsPath}")
315 squirreljme_decode_file(HEX
316 "${inFileAbs}" "${outFileAbsPath}")
320 squirreljme_write_file_checksum(
321 "${inFileAbs}" "${outFileAbsPath}")
324 "File ${outFileAbsPath} already decoded...")
329 # Sourceize a single file
330 function(squirreljme_sourceize_file inputPath
331 outputCPath outputHPath)
332 # Get the base name of the input file
333 get_filename_component(inputPathBaseName
336 # Where is the encoder?
337 squirreljme_util(sourceizeExePath sourceize)
340 execute_process(COMMAND "${sourceizeExePath}"
341 "${inputPathBaseName}" "C"
342 INPUT_FILE "${inputPath}"
343 OUTPUT_FILE "${outputCPath}"
344 RESULT_VARIABLE sourceizeExitCode
346 execute_process(COMMAND "${sourceizeExePath}"
347 "${inputPathBaseName}" "H"
348 INPUT_FILE "${inputPath}"
349 OUTPUT_FILE "${outputHPath}"
350 RESULT_VARIABLE sourceizeExitCode
354 if(sourceizeExitCode)
356 "Sourceize failed: ${sourceizeExitCode}.")
360 # Sourceize an entire directory
361 function(squirreljme_sourceize_dir inputDir outputDir)
362 # Encode all file accordingly
363 file(GLOB inFiles "${inputDir}/*")
364 foreach(inFile ${inFiles})
365 # Determine the base name of the file
366 get_filename_component(baseName
369 # Make sure the target directory exists first
370 file(MAKE_DIRECTORY "${outputDir}")
372 # Determine input and output
373 get_filename_component(inFileAbs
374 "${inFile}" ABSOLUTE)
375 get_filename_component(outFileAbsPath
376 "${outputDir}/${baseName}" ABSOLUTE)
378 # Check if source file is up to date
379 squirreljme_check_file_checksum(upToDate
380 "${inFileAbs}" "${outFileAbsPath}.c")
382 # Do the same for the header file
383 squirreljme_check_file_checksum(upToDate
384 "${inFileAbs}" "${outFileAbsPath}.h")
387 # Does decoding need to be rerun?
389 # Run decoding sequence
391 "Sourceizing ${inFileAbs} to "
392 "${outFileAbsPath}.[ch]...")
393 file(REMOVE "${outFileAbsPath}.c")
394 file(REMOVE "${outFileAbsPath}.h")
395 squirreljme_sourceize_file("${inFileAbs}"
396 "${outFileAbsPath}.c" "${outFileAbsPath}.h")
399 squirreljme_write_file_checksum(
400 "${inFileAbs}" "${outFileAbsPath}.c")
401 squirreljme_write_file_checksum(
402 "${inFileAbs}" "${outFileAbsPath}.h")
405 "File ${outFileAbsPath}.c already sourceized...")
410 # Set variable for dynamic library import
411 macro(squirreljme_library_set var target)
414 "${SQUIRRELJME_UTIL_DIR}/${SQUIRRELJME_HOST_DYLIB_PREFIX}${target}.lib")
417 "${SQUIRRELJME_UTIL_DIR}/${SQUIRRELJME_HOST_DYLIB_PREFIX}${target}${SQUIRRELJME_HOST_DYLIB_SUFFIX}")