Background
My current workflow to create/process markdown documents uses Sublime Text 2 with a Makefile build system, which calls pandoc to process them into PDF documents.
I've recently purchased a new mac, running OSX 10.8.5, and I've been running into some problems.
What's working:
I've installed Sublime Text 2, make (from xcode command line tools) and Pandoc (using the package on the website, as the cabal version wouldn't build for me).
What's not working:
When I try and build documents, it fails with the following error message from make:
pandoc -V geometry:margin=1in -S -o project_specification.pdf project_specification.markdown
make: pandoc: No such file or directory
[Finished in 0.0s with exit code 2]make: *** [project_specification.pdf] Error 1
The makefile however build absolutely fine if I run it using make at the terminal.
I think this is a problem with my path, however I'm really not sure how to set it. My understanding is that OSX has multiple paths for different applications (odd to me, as a Linux user until now), and I'm not sure how to set it for sublime to get it to work.
More background:
The makefile:
CPP_FILES = $(wildcard *.markdown)
OBJ_FILES = $(patsubst %.markdown,%.pdf,$(CPP_FILES))
%.pdf: %.markdown
pandoc -V geometry:margin=1in -S -o $# $(patsubst %.pdf,%.markdown,$#)
all: $(OBJ_FILES)
clean:
rm -f *.pdf
And finally:
I've found similar questions out there, but none with comprehensive answers, so I'm turning to stack overflow once again.
Thanks in advance for any help!
How about hack the path to wherever your pandoc is? Sublime Text 2 defaults to: /usr/bin:/bin:/usr/sbin:/sbin. This example is for a Tex Live installation using /usr/texbin, but you get the idea. There is one package that comes to mind that is more difficult to hack (e.g., Shell Turtlestein), but this works in general for most situations. I leave this running all the time when I load Sublime Text 2. If you need the turtle hack, just let me know. There are ways to adjust the path on a per package build script basis ( e.g., https://github.com/SublimeText/LaTeXTools/blob/master/LaTeX.sublime-build ), however, the following simplistic plugin usually works:
import os
LOCAL = '/usr/bin:/bin:/usr/sbin:/sbin:/usr/texbin:/usr/local/bin'
HOME = '/Users/HOME' ### !!! REPLACE WITH YOUR HOME PATH !!! ###
RVM = HOME + '/.rvm/bin:'
# Sublime's default path is
# /usr/bin:/bin:/usr/sbin:/sbin
os.environ['PATH'] += ':'
os.environ['PATH'] += LOCAL
os.environ['PATH'] += RVM
print 'PATH = ' + os.environ['PATH']
Related
I am developing in XCode on Mac OS X El Capitan 10.11.4. My project mixes C, C++11 and Embedded Python.
My project works as I can invoke a Python script and return the data to C++ by embedding python. In my project I use absolute paths as pythons search path to load the script from 'C'.
XCode project/
-- Python.framework/
-- python/
---- mypython.py
-- python_interface.c
-- main.cpp
My questions are:
Q1: I have brew Python available but this isn't seen from XCode, instead the system supplied one is. This isn't a problem for now but I would eventually like to know how to point to my chosen installation.
I have bundled the brew Python.framework into my project so it links successfully. I know it doesn't invoke this because if I specify my module path incorrectly it complains the system python can not find it. Also, 'system(which python)' reports '/usr/bin/python'.
Q2: How do I specify relative search paths to python within XCode, i.e. to locate my local python module from 'C' code within my project?
Q3: How do I determine the absolute path of python 'requests' installation at runtime? My python module imports this and it could be different than what I specify.
Currently, I use Py_GetPath and Py_SetPath to indicate these using absolute paths, i.e. '/usr/local/lib/python2.7/site-packages' for 'requests'.
I know how to locate the module path within python itself (Find path of module without importing in Python) but this is not what I want to do. I need to know the path before my script is run.
As mentioned I am embedding python, so I am making the call from 'C' to my python script (see https://docs.python.org/2/extending/embedding.html?highlight=embedded#pure-embedding).
I have found the following links that show how to get the path of the executable. What I would like is the path of the project and use relative paths from that to locate my python module.
Relative Paths Not Working in Xcode C++
Programmatically retrieving the absolute path of an OS X command-line app
I have found this posting; Relative imports for the billionth time. My search path from 'C' code to my python script is relative but I believe this post is mainly about python scripts importing other modules relative to each other.
Q4: The result of adding or linking Frameworks to an XCode project is the same. In my case the Python.framework appears in the 'Project navigator' and it is added to the 'Link Binaries With Libraries' section. Yet the following two articles indicate that there is a difference between the two. It is not the size of the executable as I have tried both methods and this remains the same.
https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_a_Framework.html
This states;
"The frameworks you add this way are third-party-built bundles containing the framework’s object code and runtime resources. See related articles for information about linking to a framework without adding it to the project."
and contains a link to "Linking to a Library or Framework", whose url seems to contradict this (AddingaLibrarytoaTarget).
https://developer.apple.com/library/ios/recipes/xcode_help-project_editor/Articles/AddingaLibrarytoaTarget.html#//apple_ref/doc/uid/TP40010155-CH17
Thanks.
Some answers to my questions
I reorganised my project and created my own Makefile using various sources on google. This was because I wanted to port my project as I couldn't answer the above questions. I had worked with Makefiles some years before but I am relatively new to XCode.
To create my Makefile these are the resources I used;
https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
C-library not linking using gcc/g++
https://www.daniweb.com/programming/software-development/threads/124637/makefile-for-c-one-file-programs
https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables
http://www.puxan.com/web/blog/HowTo-Write-Generic-Makefiles
https://www.gnu.org/software/make/manual/
http://nuclear.mutantstargoat.com/articles/make/#building-c-c-programs
https://www.gnu.org/software/make/manual/html_node/index.html
The next step is to automate the process of generating Makefiles;
http://www.ifnamemain.com/posts/2014/Mar/13/autoconf_automake/
New Makefile project structure
project/
-- Debug/ or Release/
-- Makefile
-- obj/
---- target .o files
-- python/
---- .py files
-- src/
---- C/C++ files incl headers
Makefile
# https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables
# $# Contains the target file name.
# $< Contains the first dependency file name.
# $^ The names of all the prerequisites, with spaces between them.
# Produces a Release build by default, or Debug build with ‘make debug’
EXEC = $(BUILD_DIR)/my_exe_name
CCFLAGS=-c -Wall
CXXFLAGS=-c -Wall -std=c++11
BINARY_DIR=Obj
BUILD_DIR=Release
PYTHON_CCFLAGS=$(shell python2.7-config --cflags)
PYTHON_LDFLAGS=$(shell python2.7-config --ldflags)
CPP_FILES := $(wildcard src/*.cpp)
C_FILES := $(wildcard src/*.c)
CPP_OBJ_FILES := $(addprefix $(BINARY_DIR)/,$(notdir $(CPP_FILES:.cpp=.o)))
C_OBJ_FILES := $(addprefix $(BINARY_DIR)/,$(notdir $(C_FILES:.c=.o)))
C_HEADERS = $(filter-out $(addsuffix .h, $(basename $(SOURCE_FILES))), $(wildcard src/*.h))
CPP_HEADERS = $(filter-out $(addsuffix .h, $(basename $(SOURCE_FILES))), $(wildcard src/*.hpp))
### Take the BUILD_DIR as a dependency but ignore it’s timestamp
### as it will change whenever something is written into it
$(EXEC): $(C_OBJ_FILES) $(CPP_OBJ_FILES) | ${BUILD_DIR}
#echo [ $(EXEC) ]
$(CXX) $(LD_FLAGS) $(PYTHON_LDFLAGS) -o $(EXEC) $^
### The objects in the BINARY_DIR folder require the BINARY_DIR to be created
### as well as any changes to the other dependencies
$(BINARY_DIR)/%.o: src/%.cpp $(CPP_HEADERS) $(C_HEADERS) | ${BINARY_DIR}
#echo [ make $# ]
$(CXX) $(CXXFLAGS) $(C11_FLAGS) -o $# $<
$(BINARY_DIR)/%.o: src/%.c $(C_HEADERS) | ${BINARY_DIR}
#echo [ make $# ]
$(CC) $(CCFLAGS) $(PYTHON_CCFLAGS) -o $# $<
${BINARY_DIR}:
mkdir $(BINARY_DIR)
$(BUILD_DIR):
mkdir $(BUILD_DIR)
### clean the targets. We can have either Debug or Release but I don’t know
### how to specify either in one line, i.e. we don’t want to do ‘make clean debug’
### to specify the Debug folder
.PHONY: clean cleanmsg cleanrel cleandeb
clean: cleanmsg cleanrel cleandeb
rm -r -f $(BINARY_DIR)
cleanmsg:
#echo Cleaning product and all .o files
cleanrel:
rm -r -f Release
cleandeb:
rm -r -f Debug
# Debug build
# Ensure these are last. I had them below the original decl of the flags
# and they were always set! Now you have to ‘make debug’ for it to take effect
.PHONY: debug
debug: CCFLAGS += -DDEBUG -g
debug: CXXFLAGS += -DDEBUG -g
debug: BUILD_DIR=Debug
debug: $(EXEC)
Using XCode with new Makefile project
To continue using XCode to develop my project I created an XCode project over my Makefile project. See http://hiltmon.com/blog/2015/08/01/simple-c-plus-plus-from-makefiles-to-xcode-builds/
Answers
By doing this I am able to somewhat answer the above questions. Q3 is still unanswered.
A1: Create a Makefile project and within it state the platform specified python installation. This way you do not need to bundle it into your XCode project.
See https://docs.python.org/2/extending/embedding.html?highlight=embedded#compiling-and-linking-under-unix-like-systems.
A2: Make the XCode project relative so your product resides in your project. Not the best answer if you want your exe installed in /usr/local/bin.
See How to change output directory for a target (gp_coder's answer).
My Makefile stores the exe in either ./Release/ (make), or ./Debug/ (make debug). So does XCode but with different leading directories that are several levels deep. To change this, simply specify the current dir '.' in XCode for the Targets "Project Settings>Advanced>Custom>Products" destination directory, this will then match the Makefile.
My python search path is set to
:../python:/usr/local/lib/python2.7/site-packages
'../' because my exe is in ./Debug or./Release and python/ is relative to that.
However, if you were to invoke the exe from the cmdline one dir up it wouldn't work. e.g. ./Release/my_exe_name. This is because it is taking the current dir and using the search path in relation to that.
It would be better to store and set the absolute path. See Where to store application data (non-user specific) on Linux
I posted a question on this before I realised the answer; How to set relative project path in XCode when target is /usr/local/bin
The second path is for my python requests directory. Q3 refers to this.
A3: Don't know. Still have to work out how to pass my installed python module path into my C code at runtime BEFORE invoking python, as this makes up my python search path. This value changes based on your installation.
A4: This wasn't really a question but a confusion. Specify this in your Makefile to avoid bundling.
All,
I'm trying to pass variables to make from the command line. My command is below
make ARCH=arm CROSS_COMPILE=/my_dir/bin/arm-openwrt-linux-g++
The error I received is
g++: error: arm: No such file or directory
But the file 'arm-openwrt-linux-g++' does exist.
I think the problem is I need to pass varibale to sub-make files. Can some help with an example of how to pass varialbes to sub-makefile from the command-line. I have tried using the -e and export options for make, but can't seen to get anything to work.
Thanks
Content of makefile:
# GNU Make solution makefile autogenerated by Premake
# Type "make help" for usage help
ifndef config
config=debug
endif
export config
PROJECTS := json openjaus
.PHONY: all clean help $(PROJECTS)
all: $(PROJECTS)
json:
#echo "==== Building json ($(config)) ===="
#${MAKE} --no-print-directory -C .build -f json.make
openjaus: json
#echo "==== Building openjaus ($(config)) ===="
#${MAKE} --no-print-directory -C .build -f openjaus.make
So, your problem is not related to sending variables over the command line.
Your problem is that in one of the makefiles in your sub-directories, which you haven't shown us, you're using the variable $(ARCH) in an incorrect way such that the expansion of the command line is not a legal g++ command line.
Based on the error message, most likely you're adding a space somewhere where it shouldn't be, so instead of something like -fmarch=arm you're getting -fmarch= arm. Obviously this is just an example because you didn't provide nearly enough information.
One other note: we can't know how your makefiles work but typically makefiles that support a variable like CROSS_COMPILE expect it to be set to just the prefix of the cross-compilation command; in your case it would be CROSS_COMPILE=/my_dir/bin/arm-openwrt-linux-. But, your makefiles might be different.
When asking questions, it's best to if you don't immediately jump to a guess about what the answer is. First describe the problem, and that includes showing the error line as well as a few lines before it. For example in this case you're getting an error from g++ so the command line that make printed out showing you how it invoked g++ would have helped greatly.
Once you've given the underlying detail, then if you think you have an idea about what the problem is go ahead and suggest it, and/or ask about it.
If you provide the rule that invokes g++ and/or the output from make showing the g++ command line, then we can help more.
Cheers!
Here's what I think needs to happen:
You need to make sure that your sub-makefiles actually respect the $(ARCH) and $(CROSS_COMPILE) variables. Are they also generated by Premake? If so, is that how it handles cross-compilation? Check the docs.
In my test (below), I found that variables set on the command line are propagated to sub-makes, which makes me think that your sub-makefiles aren't respecting $(ARCH):
Makefile:
a:
$(MAKE) -C z
z/Makefile:
a:
#echo "MAKE=$(MAKE)"
#echo "ARCH=$(ARCH)"
Running make with no arguments:
$ make
make -C z
make[1]: Entering directory `/home/foo/test/z'
MAKE=make
ARCH=
make[1]: Leaving directory `/home/foo/test/z'
Running make ARCH=bar:
$ make ARCH=bar
make -C z
make[1]: Entering directory `/home/foo/z/z'
MAKE=make
ARCH=bar
make[1]: Leaving directory `/home/foo/z/z'
I'm writing a Ruby C Extension. I will be compiling it under Windows and OSX.
What I have been unable to work out is control where the makefile and all the rest of the generated files are placed.
My extconf.rb file got conditional statements for preparing the makefile depending on the OS - so I use one for both of them.
I would like that when I compile under OSX it is all placed in an osx folder and similary under a win folder under Windows in order to keep it all separated.
As it is now all the files are generated in the same folder as my source code.
(I am very green to C and compiling applications. sorry if I have missed something obvious.)
I could write a batch to move the files afterwards, but I find it cleaner if it could be done during generation.
You could put a conditional in the makefile, before the rules. Something like:
OS := $(shell uname)
ifeq ($(OS),Darwin)
FOLDER := /some_path/osx_folder
else
FOLDER := /some_other_path/win_folder
endif
EDIT:
FOLDER is just a variable; it is to be used later in the makefile, like so:
$(FOLDER)/main: $(FOLDER)/main.o $(FOLDER)/foo.o
blah blah link $^ together to build $#
$(FOLDER)/%.o: $(SOURCE_DIRECTORY)/%.c
blah blah compile $< to build $#
(This is a crude example-- more elegant solutions are possible if you have a lot of files to deal with.)
I looked at the source of mkfm.rb and found that if you changed the current directory the Makefile was the current one.
Dir.chdir( OUTPUT_PATH )
create_makefile( EXTENSION_NAME, SOURCE_PATH )
That created the makefile in OUTPUT_PATH. As you see, I then had to provide SOURCE_PATH to create_makefile to account for the face the Makefile wasn't in the same location as the source files.
Is it possible to tell make to only build a target if it's sources md5 checksum has changed (instead of the edit time)?
I'm using make to compile my .tex files and I need to prevent it from building everything twice all the time.
I've tried using Scons, but I feel this isn't adaptable to other needs I have.
No, this is not supported by Make — as you've found out, support for this feature is one of the reasons why tools like Scons exist.
I found a manual recipe for GNU make, though. Maybe you can use that as a work around.
I found 3 ways: From simply
Using temporary md5-files over an
elegant but unreadable hack to
patching GNU Make yourself
(from patchy but simple to clean but hard to realize)
Maybe my scons latex and org-mode recipe helps you:
## I need a couple of special builders for my projects
# the $SOURCE replacement only uses the first source file. $SOURCES gives all.
# specifying all source files makes it possible to rerun the build if a single source file changed.
orgexportpdf = 'emacs --batch --visit "$SOURCE" --funcall org-export-as-pdf'
pyxplot = 'pyxplot $SOURCE'
# pdflatex is quite dirty. I directly clean up after it with rm.
pdflatex = 'pdflatex $SOURCE -o $TARGET; rm -f *_flymake* flymake* *.log *.out *.toc *.aux *.snm *.nav *.vrb'
# build the PhD thesis from emacs org-mode.
Command("doktorarbeit.pdf", "doktorarbeit.org",
orgexportpdf)
# create plots
Command(["images/comp-t3-s07-tem-boas.png",
"images/comp-t3-s07-tem-bona.png"],
["nee-comp.pyx",
"nee-comp.txt"],
pyxplot)
# build my sink.pdf
Command("sink.pdf",
["sink.tex",
"images/comp-t3-s07-tem-boas.png",
"images/comp-t3-s07-tem-bona.png",
"images/bona-marble.png",
"images/boas-marble.png"],
pdflatex)
# My editors leave tempfiles around. I want them gone after a build clean. This is not yet supported!
tempfiles = Glob('*~') + Glob('#*#') + Glob('*.bak')
# using this here would run the cleaning on every run.
#Command("clean", [], Delete(tempfiles))
It is the counterpart for my Makefile:
all: doktorarbeit.pdf sink.pdf
sink.pdf : sink.tex images/comp-t3-s07-tem-boas.png images/comp-t3-s07-tem-bona.png images/bona-marble.png images/boas-marble.png
pdflatex sink.tex
rm -f *_flymake* flymake* *.log *.out *.toc *.aux *.snm *.nav *.vrb # kill litter
comp-t3-s07-tem-boas.png comp-t3-s07-tem-bona.png : nee-comp.pyx nee-comp.txt
pyxplot nee-comp.pyx
# http://www.reddit.com/r/emacs/comments/dy9yt/anyone_know_of_a_script_that_i_can_feed_an/
# http://blog.nguyenvq.com/2010/10/30/bash-batch-script-to-convert-org-mode-file-to-html/comment-page-1/#comment-27013
doktorarbeit.pdf : doktorarbeit.org
emacs --batch --visit "doktorarbeit.org" --funcall org-export-as-pdf
# this is not what clean is intended to do, but I do it anyway.
clean :
rm -f \#* *~ *.bak # kill editor backups
# alternatively run scons. Should I switch to SCons, just put this in all :)
sconsrun : scons
python scons/bootstrap.py -Q
scons :
hg clone https://bitbucket.org/ArneBab/scons
I have a Makefile of the following content:
NUMBERS = 1 2 3 4
lib:
$(foreach var,$(NUMBERS),./a.out $(var);)
And this is the command that I run ( in the same directory as the Makefile)
make -f Makefile
But I got an error message saying that "The system cannot find the file specified".
Following the suggestion of one of the answers, I created the following file inside the same directory as the Makefile:
a.out
1.out
2.out
3.out
4.out
Now the error becomes:
./a.out 1; ./a.out 2; ./a.out 3;
./a.out 4; make (e=-1): Error -1 make:
*** [lib] Error -1
Note: I am running on Windows XP platform
The purpose of make is to create (and update) target files that depends on source files by running commands.
Here, the problem is with the command that is run. You are trying to run (through make) the command a.out but it does not exist, or is not an executable command. Try to replace a.out in your makefile by the actual executable command you want to run.
On Windows/DOS, use && instead of ; to join multiple commands on one line. You have to manually include a final command or the trailing && will throw a syntax error. Try something like:
NUMBERS = 1 2 3 4
lib:
$(foreach var,$(NUMBERS),.\a.out $(var) && ) echo.
It seems to me that the error comes because the file a.out cannot be located and not because the makefile could not be found.
Also if the name of your makefile is "Makefile" just invoking "make" is enough (without using -f option) as make by default would look for a file by names: GNUmakefile, makefile, and Makefile in that order.
Just what are you trying to do?
It seems to me that a plain script would be better suited rather than using make.
I found the answer by bta most useful, but it didn't work for me on both Windows and Linux, so I found a way to remove the final &&, which avoids the need for a no-op command that works on both platforms:
NUMBERS = 1 2 3 4
lib:
$(filter-out &&EOL, $(foreach var,$(NUMBERS), .\a.out $(var) &&)EOL)
Of course be careful of elements within your array matching &&EOL, but in my case, this isn't a problem.