git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: simpler make system (cmake no longer needed)
b075b42Andy Arvanitis
pcc/Main.hs+2
@@ -37,6 +37,7 @@ import qualified Language.PureScript as P
37import qualified Paths_purescript as Paths
37import qualified Paths_purescript as Paths
38
38
39import Make
39import Make
40+import Makefile
40
41
41data PCCOptions = PCCOptions
42data PCCOptions = PCCOptions
42 { pccmInput :: [FilePath]
43 { pccmInput :: [FilePath]
@@ -52,6 +53,7 @@ data InputOptions = InputOptions
52
53
53compile :: PCCOptions -> IO ()
54compile :: PCCOptions -> IO ()
54compile (PCCOptions input _ outputDir opts usePrefix) = do
55compile (PCCOptions input _ outputDir opts usePrefix) = do
56+ when (null input) generateMakefile
55 moduleFiles <- readInput (InputOptions input)
57 moduleFiles <- readInput (InputOptions input)
56 case runWriterT (parseInputs moduleFiles []) of
58 case runWriterT (parseInputs moduleFiles []) of
57 Left errs -> do
59 Left errs -> do
pcc/Make.hs−13
@@ -119,7 +119,6 @@ buildMakeActions outputDir filePathMap usePrefix =
119 let supportDir = outputDir </> "PureScript"
119 let supportDir = outputDir </> "PureScript"
120 supportFilesExist <- dirExists supportDir
120 supportFilesExist <- dirExists supportDir
121 when (not supportFilesExist) $ do
121 when (not supportFilesExist) $ do
122− writeTextFile (outputDir </> "CMakeLists.txt") (fromString cmakeListsTxt)
123 writeTextFile (supportDir </> "PureScript.hh") $ B.unpack $(embedFile "pcc/include/purescript.hh")
122 writeTextFile (supportDir </> "PureScript.hh") $ B.unpack $(embedFile "pcc/include/purescript.hh")
124 writeTextFile (supportDir </> "PureScript.cc") $ B.unpack $(embedFile "pcc/include/purescript.cc")
123 writeTextFile (supportDir </> "PureScript.cc") $ B.unpack $(embedFile "pcc/include/purescript.cc")
125
124
@@ -173,15 +172,3 @@ buildMakeActions outputDir filePathMap usePrefix =
173
172
174dotsTo :: Char -> String -> String
173dotsTo :: Char -> String -> String
175dotsTo chr = map (\c -> if c == '.' then chr else c)
174dotsTo chr = map (\c -> if c == '.' then chr else c)
176−
177−-- TODO: quick and dirty for now -- explicit file list would be better
178−cmakeListsTxt :: String
179−cmakeListsTxt = intercalate "\n" lines'
180− where lines' = [ "cmake_minimum_required (VERSION 3.0)"
181− , "project (Main)"
182− , "file (GLOB_RECURSE SRCS *.cc)"
183− , "file (GLOB_RECURSE HDRS *.hh)"
184− , "add_executable (Main ${SRCS} ${HDRS})"
185− , "include_directories (${CMAKE_CURRENT_SOURCE_DIR})"
186− , "set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} \"-std=c++11 -DDEBUG\")"
187− ]
pcc/Makefilenew file+61
@@ -0,0 +1,61 @@
1+# PureScript to native binary (via C++) Makefile
2+#
3+# Run 'make' or 'make release' to build an optimized release build
4+# Run 'make debug' to build a non-optimized build suitable for debugging
5+#
6+# You can also perform a parallel build with 'make -jN', where N is the
7+# number of cores to use.
8+#
9+# PCC, PURESCRIPT_PKGS, OUTPUT, and BIN can all be overridden with the
10+# command itself. For example: 'make PURESCRIPT_PKGS=../gitpackages BIN=myexe'
11+#
12+# Flags can be added to either the codegen or native build phases.
13+# For example: 'make PCCFLAGS=--no-tco CXXFLAGS=-DDEBUG LDFLAGS=lobjc'
14+#
15+# You can also edit the generated version of this file directly.
16+#
17+PCC := {bin/pcc} # example: /usr/local/bin/pcc
18+PURESCRIPT_PKGS := packages # example: bower_components
19+PURESCRIPT_SRC := src
20+OUTPUT := output
21+BIN := main
22+
23+override PCCFLAGS += --comments
24+override CXXFLAGS += -std=c++11
25+override LDFLAGS +=
26+
27+DEBUG := "-DDEBUG -g"
28+RELEASE := "-O3 -flto"
29+
30+PURESCRIPT_PKG_SRCS := $(shell find $(PURESCRIPT_PKGS) -name '*.purs' | grep -v \/test\/ | grep -v \/example\/ | grep -v \/examples\/)
31+PURESCRIPT_SRCS := $(shell find $(PURESCRIPT_SRC) -name '*.purs')
32+
33+INCLUDES := -I $(OUTPUT)
34+BIN_DIR := $(OUTPUT)/bin
35+
36+release: codegen
37+ $(MAKE) $(BIN) CXXFLAGS=$(RELEASE)
38+
39+debug: codegen
40+ $(MAKE) $(BIN) CXXFLAGS=$(DEBUG)
41+
42+codegen:
43+ $(PCC) $(PCCFLAGS) --output $(OUTPUT) $(PURESCRIPT_PKG_SRCS) $(PURESCRIPT_SRCS)
44+
45+SRCS := $(shell find $(OUTPUT) 2>/dev/null -name '*.cc')
46+
47+OBJS = $(SRCS:.cc=.o)
48+DEPS = $(SRCS:.cc=.d)
49+
50+$(BIN): $(OBJS)
51+ @mkdir -p $(BIN_DIR)
52+ $(CXX) $(LDFLAGS) $^ -o $(BIN_DIR)/$@
53+
54+-include $(DEPS)
55+
56+%.o: %.cc
57+ $(CXX) $(CXXFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@
58+
59+.PHONY: clean
60+clean:
61+ @-rm -rf $(OUTPUT)
pcc/Makefile.exampledeleted−19
@@ -1,19 +0,0 @@
1−PCC := "../.cabal-sandbox/bin/pcc"
2−
3−MODULE_DIR="../../packages"
4−#MODULE_DIR="bower_components"
5−SOURCE_DIR="src"
6−
7−MODULES := $(shell find $(MODULE_DIR) -name '*.purs' | grep -v \/test\/ | grep -v \/example\/ | grep -v \/examples\/)
8−SOURCES := $(shell find $(SOURCE_DIR) -name '*.purs')
9−
10−all: Main
11−
12−Main: src/*
13− $(PCC) $(MODULES) $(SOURCES)
14− @mkdir -p build && cd build && cmake ../output && $(MAKE) && cp Main ../
15−
16−clean:
17− @rm -f Main
18− @rm -rf output
19− @rm -rf build
pcc/Makefile.hsnew file+50
@@ -0,0 +1,50 @@
1+-------------------------------------------------------------------------------
2+--
3+-- Module : Main
4+-- Copyright : (c) 2016 Andy Arvanitis and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Andy Arvanitis
8+-- Stability : experimental
9+-- Portability :
10+--
11+-------------------------------------------------------------------------------
12+{-# LANGUAGE OverloadedStrings #-}
13+{-# LANGUAGE TemplateHaskell #-}
14+
15+module Makefile where
16+
17+import Control.Monad (when)
18+import Data.FileEmbed (embedFile)
19+import Data.List
20+import System.Environment (getExecutablePath)
21+import System.Directory (doesFileExist)
22+
23+import qualified Data.ByteString.Char8 as B
24+
25+generateMakefile :: IO ()
26+generateMakefile = do
27+ makefileExists <- doesFileExist "Makefile"
28+ when (not makefileExists) $ do
29+ let makefile = $(embedFile "pcc/Makefile")
30+ exePath <- getExecutablePath
31+ putStrLn ""
32+ putStrLn "Generating Makefile..."
33+ putStrLn $ "pcc executable location: " ++ exePath
34+ writeFile "Makefile" $ replace makefile pccPath exePath
35+ putStrLn "Done"
36+ putStrLn "Run 'make' or 'make release' to build an optimized release build."
37+ putStrLn "The resulting binary executable will be located in output/bin (by default)."
38+ putStrLn ""
39+
40+replace :: B.ByteString -> B.ByteString -> String -> String
41+replace s orig repl = replace'
42+ where
43+ replace'
44+ | (p1, p2) <- B.breakSubstring orig s,
45+ not (B.null p2) = B.unpack p1 ++ repl ++ trim (B.unpack p2)
46+ | otherwise = B.unpack s
47+ trim = drop (B.length orig)
48+
49+pccPath :: B.ByteString
50+pccPath = "{bin/pcc}"
pcc/TestMain.hs+9−29
@@ -44,34 +44,30 @@ main = do
44 let srcDir = outputDir </> "src"
44 let srcDir = outputDir </> "src"
45 createDirectory srcDir
45 createDirectory srcDir
46
46
47− let buildDir = outputDir </> "build"
48− createDirectory buildDir
49−
50− let makefile = outputDir </> "Makefile"
51− writeFile makefile makefileText
52−
53 let passingDir = baseDir </> "examples" </> "passing"
47 let passingDir = baseDir </> "examples" </> "passing"
54 passingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents passingDir
48 passingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents passingDir
55
49
50+ -- Auto-generate Makefile
51+ setCurrentDirectory outputDir
52+ callProcess "../.cabal-sandbox/bin/pcc" []
53+
56 let tests = filter (`notElem` skipped) passingTestCases
54 let tests = filter (`notElem` skipped) passingTestCases
57
55
58 -- Run the tests
56 -- Run the tests
59 --
57 --
60 forM_ tests $ \inputFile -> do
58 forM_ tests $ \inputFile -> do
61 --
59 --
62− -- Compile PureScript file
60+ -- Compile/build
63 --
61 --
64 putStrLn $ "Compiling test " ++ inputFile ++ " ..."
62 putStrLn $ "Compiling test " ++ inputFile ++ " ..."
65 setCurrentDirectory outputDir
63 setCurrentDirectory outputDir
66 copyFile (passingDir </> inputFile) (srcDir </> inputFile)
64 copyFile (passingDir </> inputFile) (srcDir </> inputFile)
67− callProcess "make" ["clean", "main"]
65+ callProcess "make" ["clean"]
66+ callProcess "make" ["debug"]
68 --
67 --
69− -- Build and run C++ files
68+ -- Run C++ files
70 --
69 --
71− setCurrentDirectory buildDir
72− callProcess "cmake" ["../output"]
70+ callProcess ("output" </> "bin" </> "main") []
73− callProcess "make" []
74− callProcess (buildDir </> "Main") []
75
71
76 removeFile (srcDir </> inputFile)
72 removeFile (srcDir </> inputFile)
77
73
@@ -116,22 +112,6 @@ fetchPackages = do
116 callProcess "git" $ ["clone"] ++ (if null branch then [] else ["--branch", branch]) ++ [repo ++ (fst package) ++ ".git"]
112 callProcess "git" $ ["clone"] ++ (if null branch then [] else ["--branch", branch]) ++ [repo ++ (fst package) ++ ".git"]
117 setCurrentDirectory baseDir
113 setCurrentDirectory baseDir
118
114
119−-------------------------------------------------------------------------------
120−makefileText :: String
121−-------------------------------------------------------------------------------
122−makefileText = intercalate "\n" lines'
123− where lines' = [ "PCC := '../.cabal-sandbox/bin/pcc'"
124− , "MODULE_DIR='packages'"
125− , "SOURCE_DIR='src'"
126− , "MODULES := $(shell find $(MODULE_DIR) -name '*.purs' | grep -v \\/test\\/ | grep -v \\/example\\/ | grep -v \\/examples\\/)"
127− , "SOURCES := $(shell find $(SOURCE_DIR) -name '*.purs')"
128− , "all: main"
129− , "main:"
130− , "\t$(PCC) $(MODULES) $(SOURCES)"
131− , "clean:"
132− , "\t@rm -rf output/*"
133− ]
134−
135-------------------------------------------------------------------------------
115-------------------------------------------------------------------------------
136skipped :: [String]
116skipped :: [String]
137-------------------------------------------------------------------------------
117-------------------------------------------------------------------------------