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)
13 # The directory where the utilities should exist
14 get_filename_component(SQUIRRELJME_UTIL_SOURCE_DIR
15 "${CMAKE_SOURCE_DIR}/cmake/utils" ABSOLUTE)
16 get_filename_component(SQUIRRELJME_UTIL_DIR
17 "${CMAKE_BINARY_DIR}/utils" ABSOLUTE)
19 # Add macro to determine the path of a utility
20 macro(squirreljme_util var what)
22 "${SQUIRRELJME_UTIL_DIR}/${what}${SQUIRRELJME_HOST_EXE_SUFFIX}")
25 # Only run this if the directory does not exist, because there might be a
26 # cache from a previous run?
27 if(NOT EXISTS "${SQUIRRELJME_UTIL_DIR}" OR
28 NOT EXISTS "${SQUIRRELJME_UTIL_DIR}/CMakeCache.txt")
29 # Make sure the directory exists
30 file(MAKE_DIRECTORY "${SQUIRRELJME_UTIL_DIR}")
32 # Emscripten breaks here, so do not use it with nested CMake
33 # Also nested CMake breaks here as well
34 if(EMSCRIPTEN OR SQUIRRELJME_CROSS_BUILD)
35 set(cmakeUtilConfigResult 1)
38 message(STATUS "Bootstrapping utils into "
39 "${SQUIRRELJME_UTIL_DIR}...")
40 message(STATUS "Current generator is ${CMAKE_GENERATOR}...")
42 # Run nested CMake to build the utilities
43 if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13")
44 # CMake 3.13 added the -S and -B switches
46 COMMAND "${CMAKE_COMMAND}"
48 "--unset=CMAKE_TOOLCHAIN_FILE"
49 "--unset=CMAKE_SOURCE_ROOT"
50 "--unset=CMAKE_FRAMEWORK_PATH"
51 "--unset=CMAKE_INCLUDE_PATH"
52 "--unset=CMAKE_LIBRARY_PATH"
53 "--unset=CMAKE_PROGRAM_PATH"
54 "--unset=CMAKE_BUILD_TYPE"
55 "--unset=CMAKE_GENERATOR"
56 "--unset=CMAKE_GENERATOR_INSTANCE"
57 "--unset=CMAKE_GENERATOR_PLATFORM"
58 "--unset=CMAKE_GENERATOR_TOOLSET"
59 "--unset=CMAKE_C_COMPILER_LAUNCHER"
60 "--unset=CMAKE_C_LINKER_LAUNCHER"
63 "-DCMAKE_BUILD_TYPE=Debug"
64 "-G" "${CMAKE_GENERATOR}"
65 "-S" "${SQUIRRELJME_UTIL_SOURCE_DIR}"
66 "-B" "${SQUIRRELJME_UTIL_DIR}"
67 RESULT_VARIABLE cmakeUtilBuildResult)
69 # Need to initialize the project the old way, by just being in
70 # a different working directory and referring to the source
72 COMMAND "${CMAKE_COMMAND}"
74 "--unset=CMAKE_TOOLCHAIN_FILE"
75 "--unset=CMAKE_SOURCE_ROOT"
76 "--unset=CMAKE_FRAMEWORK_PATH"
77 "--unset=CMAKE_INCLUDE_PATH"
78 "--unset=CMAKE_LIBRARY_PATH"
79 "--unset=CMAKE_PROGRAM_PATH"
80 "--unset=CMAKE_BUILD_TYPE"
81 "--unset=CMAKE_GENERATOR"
82 "--unset=CMAKE_GENERATOR_INSTANCE"
83 "--unset=CMAKE_GENERATOR_PLATFORM"
84 "--unset=CMAKE_GENERATOR_TOOLSET"
85 "--unset=CMAKE_C_COMPILER_LAUNCHER"
86 "--unset=CMAKE_C_LINKER_LAUNCHER"
89 "-DCMAKE_BUILD_TYPE=Debug"
90 "-G" "${CMAKE_GENERATOR}"
91 "${SQUIRRELJME_UTIL_SOURCE_DIR}"
92 WORKING_DIRECTORY "${SQUIRRELJME_UTIL_DIR}"
93 RESULT_VARIABLE cmakeUtilConfigResult)
98 if(cmakeUtilConfigResult)
99 message(WARNING "Cannot configure utils: "
100 "${cmakeUtilConfigResult}...")
102 # Determine executable suffix
103 if(EXISTS "${SQUIRRELJME_UTIL_DIR}/suffix")
104 file(STRINGS "${SQUIRRELJME_UTIL_DIR}/suffix"
105 SQUIRRELJME_HOST_EXE_SUFFIX)
106 message(DEBUG "Host executable suffix is "
107 "'${SQUIRRELJME_HOST_EXE_SUFFIX}'.")
112 "No need to configure utilities, already there...")
113 set(cmakeUtilConfigResult 0)
116 if (NOT cmakeUtilConfigResult AND
118 # Build the utilities, just in case it is out of date
119 message(STATUS "Building utilities, if out of date...")
121 COMMAND "${CMAKE_COMMAND}"
122 "--build" "${SQUIRRELJME_UTIL_DIR}"
123 RESULT_VARIABLE cmakeUtilBuildResult
124 WORKING_DIRECTORY "${SQUIRRELJME_UTIL_DIR}")
126 # Make sure the executable actually runs since it might have built
127 if(NOT cmakeUtilBuildResult)
128 # Determine path where simple exists
129 squirreljme_util(cmakeSimpleExe simple)
131 # Execute it and check if it works
132 execute_process(COMMAND "${cmakeSimpleExe}"
133 RESULT_VARIABLE cmakeUtilBuildResult
134 WORKING_DIRECTORY "${SQUIRRELJME_UTIL_DIR}")
136 if(cmakeUtilBuildResult)
137 message(WARNING "Failed to run simple test utility.")
139 message(STATUS "Simple test ran okay.")
143 set(cmakeUtilBuildResult 1)
147 if(cmakeUtilBuildResult)
149 message(WARNING "Cannot build and run utils (CMake): "
150 "${cmakeUtilBuildResult}...")
152 # Try to find a compiler
153 find_program(HOST_CC "cc")
155 find_program(HOST_CC "gcc")
158 # Fallback to regular make, maybe it will work
160 COMMAND "${CMAKE_COMMAND}"
169 "OUTPUT_DIR=${SQUIRRELJME_UTIL_DIR}"
170 "HOST_EXE_SUFFIX=${SQUIRRELJME_HOST_EXE_SUFFIX}"
171 RESULT_VARIABLE makeUtilBuildResult
172 WORKING_DIRECTORY "${SQUIRRELJME_UTIL_SOURCE_DIR}")
175 if(makeUtilBuildResult)
177 "Cannot build utils (Make): "
178 "${makeUtilBuildResult}...")
182 # If there is no suffix and we are on Windows, assume .exe
183 if(NOT DEFINED SQUIRRELJME_HOST_EXE_SUFFIX AND
184 CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
185 set(SQUIRRELJME_HOST_EXE_SUFFIX ".exe")
188 # Checks if a given file is out of date according to a checksum
189 function(squirreljme_check_file_checksum upToDateVar
190 inputFile outputPath)
191 # Get hash of input file
192 file(SHA1 "${inputFile}" cacheHash)
194 # Get last checksum, if any
195 if(EXISTS "${outputPath}.checksum")
196 file(STRINGS "${outputPath}.checksum"
199 set(cacheHashLast "")
202 # Is the checksum out of date?
203 if(NOT EXISTS "${outputPath}.checksum" OR
204 NOT EXISTS "${outputPath}" OR
205 NOT "${cacheHash}" STREQUAL "${cacheHashLast}")
206 set(${upToDateVar} 0 PARENT_SCOPE)
208 set(${upToDateVar} 1 PARENT_SCOPE)
212 # Writes the checksum of the input file to the output
213 function(squirreljme_write_file_checksum inputFile
215 # Get hash of input file
216 file(SHA1 "${inputFile}" cacheHash)
219 file(WRITE "${outputPath}.checksum"
223 # Decodes the given file
224 function(squirreljme_decode_file how
225 inputPath outputPath)
226 # Should be HEX or BASE64
227 if(NOT how STREQUAL "HEX" AND
228 NOT how STREQUAL "BASE64")
229 message(FATAL_ERROR "squirreljme_decode_file() takes "
230 "either HEX or BASE64")
233 # Where is the decoder?
234 squirreljme_util(decodeExePath decode)
237 execute_process(COMMAND "${decodeExePath}" "${how}"
238 INPUT_FILE "${inputPath}"
239 OUTPUT_FILE "${outputPath}"
240 RESULT_VARIABLE conversionExitCode
244 if(conversionExitCode)
246 "Conversion failed: ${conversionExitCode}.")
250 # Decodes a directory of encoded files
251 function(squirreljme_decode_dir inputDir outputDir)
252 # Decode all files accordingly
254 "${inputDir}/*.__hex"
255 "${inputDir}/*.__mime")
256 foreach(inFile ${inFiles})
257 # Determine the base name of the file
258 get_filename_component(baseName
261 # Is this Hex or MIME?
262 string(FIND "${baseName}" ".__hex"
265 # Remove extension from it
266 string(REPLACE ".__hex" ""
269 string(REPLACE ".__mime" ""
273 # Make sure the target directory exists first
274 file(MAKE_DIRECTORY "${outputDir}")
276 # Determine input and output
277 get_filename_component(inFileAbs
278 "${inFile}" ABSOLUTE)
279 get_filename_component(outFileAbsPath
280 "${outputDir}/${baseName}" ABSOLUTE)
282 # Check if file is up to date
283 squirreljme_check_file_checksum(upToDate
284 "${inFileAbs}" "${outFileAbsPath}")
286 # Does decoding need to be rerun?
288 # Run decoding sequence
290 "Decoding ${inFileAbs} to "
291 "${outFileAbsPath}...")
292 file(REMOVE "${outFileAbsPath}")
294 squirreljme_decode_file(BASE64
295 "${inFileAbs}" "${outFileAbsPath}")
297 squirreljme_decode_file(HEX
298 "${inFileAbs}" "${outFileAbsPath}")
302 squirreljme_write_file_checksum(
303 "${inFileAbs}" "${outFileAbsPath}")
306 "File ${outFileAbsPath} already decoded...")
311 # Sourceize a single file
312 function(squirreljme_sourceize_file inputPath
313 outputCPath outputHPath)
314 # Get the base name of the input file
315 get_filename_component(inputPathBaseName
318 # Where is the encoder?
319 squirreljme_util(sourceizeExePath sourceize)
322 execute_process(COMMAND "${sourceizeExePath}"
323 "${inputPathBaseName}" "C"
324 INPUT_FILE "${inputPath}"
325 OUTPUT_FILE "${outputCPath}"
326 RESULT_VARIABLE sourceizeExitCode
328 execute_process(COMMAND "${sourceizeExePath}"
329 "${inputPathBaseName}" "H"
330 INPUT_FILE "${inputPath}"
331 OUTPUT_FILE "${outputHPath}"
332 RESULT_VARIABLE sourceizeExitCode
336 if(sourceizeExitCode)
338 "Sourceize failed: ${sourceizeExitCode}.")
342 # Sourceize an entire directory
343 function(squirreljme_sourceize_dir inputDir outputDir)
344 # Encode all file accordingly
345 file(GLOB inFiles "${inputDir}/*")
346 foreach(inFile ${inFiles})
347 # Determine the base name of the file
348 get_filename_component(baseName
351 # Make sure the target directory exists first
352 file(MAKE_DIRECTORY "${outputDir}")
354 # Determine input and output
355 get_filename_component(inFileAbs
356 "${inFile}" ABSOLUTE)
357 get_filename_component(outFileAbsPath
358 "${outputDir}/${baseName}" ABSOLUTE)
360 # Check if source file is up to date
361 squirreljme_check_file_checksum(upToDate
362 "${inFileAbs}" "${outFileAbsPath}.c")
364 # Do the same for the header file
365 squirreljme_check_file_checksum(upToDate
366 "${inFileAbs}" "${outFileAbsPath}.h")
369 # Does decoding need to be rerun?
371 # Run decoding sequence
373 "Sourceizing ${inFileAbs} to "
374 "${outFileAbsPath}.[ch]...")
375 file(REMOVE "${outFileAbsPath}.c")
376 file(REMOVE "${outFileAbsPath}.h")
377 squirreljme_sourceize_file("${inFileAbs}"
378 "${outFileAbsPath}.c" "${outFileAbsPath}.h")
381 squirreljme_write_file_checksum(
382 "${inFileAbs}" "${outFileAbsPath}.c")
383 squirreljme_write_file_checksum(
384 "${inFileAbs}" "${outFileAbsPath}.h")
387 "File ${outFileAbsPath}.c already sourceized...")