Browse Source

Got compile-time code execution working

* I made the mistake of not having exactly the same compilation settings
for the executable vs. the DLL.
* I wasn't specifying a dynamic runtime either, which is essential for
the DLL to share the same memory.
* My macro was missing escape characters. I need to fix that eventually
* Fix CRC -> CRT typo in readme
* Build everything in debug (cleanup coming)
Macoy Madson 6 months ago
8 changed files with 109 additions and 15 deletions
  1. +2
  2. +6
  3. +84
  4. +1
  5. +5
  6. +9
  7. +1
  8. +1

+ 2
- 1
.gitignore View File

@ -50,4 +50,5 @@ cakelisp_cache/

+ 6
- 6
Bootstrap_MSVC.cake View File

@ -20,25 +20,25 @@
(add-build-options "/DWINDOWS" "/DCAKELISP_EXPORTING" "/EHsc"
"/Zi" "/FS" "/Fd:bin\cakelisp.pdb" "/DEBUG:FASTLINK")
(add-build-options "/nologo" "/DWINDOWS" "/DCAKELISP_EXPORTING" "/EHsc"
;;; DEBUG ONLY! Note that link also needs /DEBUG
"/Zi" "/FS" "/Fd:bin\cakelisp.pdb" "/DEBUG:FASTLINK" "/MDd")
(set-cakelisp-option build-time-compiler "cl.exe")
(set-cakelisp-option build-time-compile-arguments
"/nologo" "/c" 'source-input 'object-output
"/c" 'source-input 'object-output
'include-search-dirs 'additional-options)
(set-cakelisp-option compile-time-compiler "cl.exe")
(set-cakelisp-option compile-time-compile-arguments
"/nologo" "/c" 'source-input 'object-output
"/nologo" "/DEBUG:FASTLINK" "/MDd" "/c" 'source-input 'object-output
;; "-fPIC"
;; cl.exe for linker also works
(set-cakelisp-option build-time-linker "link.exe")
(set-cakelisp-option build-time-link-arguments
"/nologo" 'executable-output 'object-input)
"/nologo" "/DEBUG:FASTLINK" 'executable-output 'object-input)
;; Use separate build configuration in case other things build files from src/
(add-build-config-label "Bootstrap_Windows")

+ 84
- 0
Build_SimpleMacros.bat View File

@ -0,0 +1,84 @@
echo off
rem Set environment variables. The user may need to adjust this path
rem See
if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" (
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
) else (
echo This script builds using MSVC.
echo You must download and install MSVC before it will work. Download it here:
echo Select workloads for C++ projects. Ensure you install the C++ developer tools.
echo If you're still seeing this, you may need to edit Build.bat to your vcvars path
echo Please see the following link:
goto fail
if not exist "bin" (
mkdir bin
if not exist "bin\cakelisp_bootstrap.exe" (
goto manualBuild
) else (
goto bootstrapBuild
CL.exe src/Tokenizer.cpp ^
src/Evaluator.cpp ^
src/Utilities.cpp ^
src/FileUtilities.cpp ^
src/Converters.cpp ^
src/Writer.cpp ^
src/Generators.cpp ^
src/GeneratorHelpers.cpp ^
src/RunProcess.cpp ^
src/OutputPreambles.cpp ^
src/DynamicLoader.cpp ^
src/ModuleManager.cpp ^
src/Logging.cpp ^
src/Build.cpp ^
src/Main.cpp ^
/Fe"bin\cakelisp_bootstrap" /Zi /Fd"bin\cakelisp_bootstrap.pdb" /DEBUG:FASTLINK
@if %ERRORLEVEL% == 0 (
echo Success building
rem Clean up working directory
del *.obj
goto bootstrapBuild
) else (
echo Error while building
goto fail
"bin\cakelisp_bootstrap.exe" Bootstrap_MSVC.cake
@if %ERRORLEVEL% == 0 (
echo Success! Use bin\cakelisp.exe to build your programs
goto build_user
) else (
echo Error while bootstrapping cakelisp
goto fail
"bin\cakelisp.exe" --verbose-processes --execute test/SimpleMacros.cake
@if %ERRORLEVEL% == 0 (
echo Success!
goto success
) else (
echo Error while building user program
goto fail
goto end
goto end

+ 1
- 1 View File

@ -136,7 +136,7 @@ You can refer to an existing project in ~cakelisp/VisualStudio~. The steps to cr
~CAKELISP_EXPORTING~ indicates Cakelisp should export its symbols to DLLs. The ~CRC~ definition is going to be removed eventually; it makes MSVC more lenient with some errors Cakelisp has. The ~WINDOWS~ definition ensures you build with Cakelisp's Windows-specific code enabled
~CAKELISP_EXPORTING~ indicates Cakelisp should export its symbols to DLLs. The ~CRT~ definition is going to be removed eventually; it makes MSVC more lenient with some errors Cakelisp has. The ~WINDOWS~ definition ensures you build with Cakelisp's Windows-specific code enabled
- Hit ~F5~ or go to ~Debug -> Start Debugging~. Visual Studio will build Cakelisp, and if it succeeds, launch Cakelisp. If you have no ~Command Arguments~ set, you should see the Cakelisp help output in a command window.
This project is for building Cakelisp itself; you don't need to make any new projects for your projects written in Cakelisp (in ~.cake~ files). Change the ~Debugging -> Command Arguments~ setting to build different Cakelisp files, or change the ~Working Directory~ to build a different Cakelisp project (e.g. one in a separate repository).

+ 5
- 1
src/Logging.hpp View File

@ -1,3 +1,7 @@
#pragma once
#include "Exporting.hpp"
struct LoggingSettings
// verbosity
@ -25,4 +29,4 @@ struct LoggingSettings
bool strictIncludes;
extern LoggingSettings logging;
extern CAKELISP_API LoggingSettings logging;

+ 9
- 4
src/ModuleManager.cpp View File

@ -82,8 +82,12 @@ void moduleManagerInitialize(ModuleManager& manager)
// Need this to properly add declspec for importing symbols
{ProcessCommandArgumentType_String, "/DWINDOWS"},
// TODO Fix
{ProcessCommandArgumentType_String, "/DEBUG"},
{ProcessCommandArgumentType_String, "/DEBUG:FASTLINK"},
{ProcessCommandArgumentType_String, "/Zi"},
// Need to use dynamic runtime so everything is shared. Cakelisp must be built with this as well
// (use just /MD for release)
// SEe
{ProcessCommandArgumentType_String, "/MDd"},
{ProcessCommandArgumentType_String, "/Fp\"cakelisp_cache\\comptime_my_print.pdb\""},
{ProcessCommandArgumentType_String, "/c"},
{ProcessCommandArgumentType_SourceInput, EmptyString},
@ -94,11 +98,12 @@ void moduleManagerInitialize(ModuleManager& manager)
manager.environment.compileTimeLinkCommand.fileToExecute = "link.exe";
manager.environment.compileTimeLinkCommand.arguments = {
{ProcessCommandArgumentType_String, "/nologo"},
{ProcessCommandArgumentType_String, "/DLL"},
{ProcessCommandArgumentType_String, "/nologo"},
{ProcessCommandArgumentType_String, "/DLL"},
{ProcessCommandArgumentType_DynamicLibraryOutput, EmptyString},
{ProcessCommandArgumentType_ObjectInput, EmptyString},
// On Windows, .exes create .lib files for exports
{ProcessCommandArgumentType_String, "/DEBUG:FASTLINK"},
// On Windows, .exes create .lib files for exports
{ProcessCommandArgumentType_String, "/LIBPATH:\"bin\""},
{ProcessCommandArgumentType_String, "cakelisp.lib"}};

+ 1
- 1
src/Tokenizer.hpp View File

@ -47,4 +47,4 @@ bool writeStringToBufferErrorToken(const char* str, char** at, char* bufferStart
const Token& token);
bool appendTokenToString(const Token& token, char** at, char* bufferStart, int bufferSize);
extern int g_totalLinesTokenized;
extern CAKELISP_API int g_totalLinesTokenized;

+ 1
- 1
test/SimpleMacros.cake View File

@ -2,7 +2,7 @@
(defmacro my-print (message string)
(printf "Compile-time print!\n")
(tokenize-push output (printf "%s\n" (token-splice message)))
(tokenize-push output (printf \"%s\\n\" (token-splice message)))
(return true))
(defun main(&return int)